﻿// NOTE: This came from CodeProject: http://www.codeproject.com/Articles/138024/Header-Editable-Tab-Control-in-WPF
// Author is Amit Kumar Dutta.
// Uses CPOL license.
//
// NOTE: Made slight behavior change to select all when the textbox gets focus.

namespace MyCompany.UserInterfaceLibrary {
	using System;
	using System.Windows;
	using System.Windows.Controls;
	using System.Windows.Input;
	using System.Windows.Threading;

	/// <summary>
	///     Header Editable TabItem
	/// </summary>
	[TemplatePart(Name = "PART_TabHeader", Type = typeof(TextBox))]
	public class EditableTabHeaderControl : ContentControl {
		/// <summary>
		///     Dependency property to bind EditMode with XAML Trigger
		/// </summary>
		static readonly DependencyProperty IsInEditModeProperty = DependencyProperty.Register("IsInEditMode", typeof(bool), typeof(EditableTabHeaderControl));

		string oldText;

		TextBox textBox;

		DispatcherTimer timer;

		/// <summary>
		///     Gets or sets a value indicating whether this instance is in edit mode.
		/// </summary>
		public bool IsInEditMode
		{
			get
			{
				return (bool)GetValue(IsInEditModeProperty);
			}
			set
			{
				if (string.IsNullOrEmpty(textBox.Text))
					textBox.Text = oldText;

				oldText = textBox.Text;
				SetValue(IsInEditModeProperty, value);
			}
		}

		/// <summary>
		///     When overridden in a derived class, is invoked whenever application code or internal processes call
		///     <see cref="M:System.Windows.FrameworkElement.ApplyTemplate" />.
		/// </summary>
		public override void OnApplyTemplate() {
			base.OnApplyTemplate();
			textBox = Template.FindName("PART_TabHeader", this) as TextBox;
			if (textBox != null) {
				timer = new DispatcherTimer();
				timer.Tick += TimerTick;
				timer.Interval = TimeSpan.FromMilliseconds(1);
				LostFocus += TextBoxLostFocus;
				textBox.KeyDown += TextBoxKeyDown;
				MouseDoubleClick += EditableTabHeaderControlMouseDoubleClick;
			}
		}

		/// <summary>
		///     Sets the IsInEdit mode.
		/// </summary>
		/// <param name="value">if set to <c>true</c> [value].</param>
		public void SetEditMode(bool value) {
			IsInEditMode = value;
			timer.Start();
		}

		void EditableTabHeaderControlMouseDoubleClick(object sender, MouseButtonEventArgs e) {
			if (e.LeftButton == MouseButtonState.Pressed)
				SetEditMode(true);
		}

		void MoveTextBoxInFocus() {
			if (textBox.CheckAccess()) {
				if (!string.IsNullOrEmpty(textBox.Text)) {
					// NOTE: Dale changes this behavior from just putting the caret at the beginning to selecting the text so that it can be replaced without using the mouse.
					textBox.SelectAll();
					//textBox.CaretIndex = 0;
					textBox.Focus();
				}
			}
			else
				textBox.Dispatcher.BeginInvoke(DispatcherPriority.Render, new FocusTextBox(MoveTextBoxInFocus));
		}

		void TextBoxKeyDown(object sender, KeyEventArgs e) {
			if (e.Key == Key.Escape) {
				textBox.Text = oldText;
				IsInEditMode = false;
			}
			else if (e.Key == Key.Enter)
				IsInEditMode = false;
		}

		void TextBoxLostFocus(object sender, RoutedEventArgs e) {
			IsInEditMode = false;
		}

		void TimerTick(object sender, EventArgs e) {
			timer.Stop();
			MoveTextBoxInFocus();
		}

		delegate void FocusTextBox();
	}
}
